import './style.less'

import { TiptapCollabProvider } from '@hocuspocus/provider'
import { Collaboration } from '@tiptap/extension-collaboration'
import { CollaborationCursor } from '@tiptap/extension-collaboration-cursor'
import Image from '@tiptap/extension-image'
import Placeholder from '@tiptap/extension-placeholder'
import { EditorContent, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { CommentsKit, hoverOffThread, hoverThread } from '@tiptap-pro/extension-comments'
import { useCallback, useRef, useState } from 'react'
import { v4 as uuid } from 'uuid'
import * as Y from 'yjs'
import { Plugin, PluginKey } from '@tiptap/pm/state'
import { isPositionSafe, safeNodeAt } from '@/utils/tiptap-utils'

import { fromBase64String } from '../demo-setup'
import { initialContent } from '../initialContent'
import { ThreadsList } from './components/ThreadsList'
import { CommentInputModal } from './components/CommentInputModal'
import { ThreadsProvider } from './context'
import { useThreads } from './hooks/useThreads'
import { useUser } from './hooks/useUser'

const doc = new Y.Doc()
// user 从localstorage中获取
const user = {
  name: localStorage.getItem('username'),
}
console.log(user)
const isDev = import.meta.env.MODE === 'development'
const id = isDev ? 'dev' : uuid()

const provider = new TiptapCollabProvider({
  appId: import.meta.env.VITE_TIPTAP_APP_ID,
  name: `tiptap-comments-demo/${id}`,
  document: doc,
  user: user, //用于对文档进行更改的用户 ID 或名称
  connect:true, //初始化后连接到服务器
  broadcast: true, // 实现跨浏览器标签页的文档同步
  preserveConnection:true, // 关闭提供程序后保持 WebSocket 连接打开

  onOpen() {
    console.log('WebSocket connection opened.')
  },
  onConnect() {
    console.log('Connected to the server.')
  },
})

// 不应用初始内容，避免解析错误
// const initialBinary = fromBase64String(initialContent)
// Y.applyUpdate(provider.document, initialBinary)

const TiptapCommentEditor = () => {
  const [showUnresolved, setShowUnresolved] = useState(true)
  const [selectedThread, setSelectedThread] = useState(null)
  const threadsRef = useRef([])

  const user = useUser()

  const editor = useEditor({
    extensions: [
      StarterKit.configure({
        history: false,
      }),
      Image,
      Collaboration.configure({
        document: doc,
      }),
      CollaborationCursor.configure({
        provider,
        user: {
          name: user.name,
          color: user.color,
        },
      }),
      CommentsKit.configure({
        provider,
        useLegacyWrapping: false,
        onClickThread: threadId => {
          console.log('CommentsKit onClickThread called with:', threadId)
          
          if (!threadId) {
            console.warn('Thread ID is null or undefined in onClickThread')
            setSelectedThread(null)
            if (editor) {
              try {
                editor.chain().unselectThread().run()
              } catch (error) {
                console.warn('Error unselecting thread:', error)
              }
            }
            return
          }

          // 验证编辑器状态
          if (!editor || !editor.state || !editor.state.doc) {
            console.warn('Editor state is not ready for thread selection')
            return
          }

          const isResolved = threadsRef.current.find(t => t.id === threadId)?.resolvedAt

          if (isResolved) {
            setSelectedThread(null)
            if (editor) {
              try {
                editor.chain().unselectThread().run()
              } catch (error) {
                console.warn('Error unselecting resolved thread:', error)
              }
            }
            return
          }

          setSelectedThread(threadId)
          if (editor) {
            try {
              editor.chain().selectThread({ id: threadId, updateSelection: false }).run()
            } catch (error) {
              console.error('Error selecting thread:', error)
              // 如果选择失败，重置状态
              setSelectedThread(null)
            }
          }
        },
      }).extend({
        // 添加安全的点击处理插件
        addProseMirrorPlugins() {
          return [
            ...this.parent?.() || [],
            new Plugin({
              key: new PluginKey('safeCommentsClick'),
              props: {
                handleClick(view, pos, event) {
                  // 在处理点击之前验证位置
                  if (!isPositionSafe({ state: view.state }, pos)) {
                    console.warn('Unsafe position detected in comment click:', pos)
                    event.preventDefault()
                    return true
                  }
                  return false
                }
              }
            })
          ]
        }
      }),
      Placeholder.configure({
        placeholder: 'Write a text to add comments …',
      }),
    ],
  })

  const { threads = [], createThread } = useThreads(provider, editor, user)

  threadsRef.current = threads

  const selectThreadInEditor = useCallback(threadId => {
    editor.chain().selectThread({ id: threadId }).run()
  }, [editor])

  const deleteThread = useCallback(threadId => {
    provider.deleteThread(threadId)
    editor.commands.removeThread({ id: threadId })
  }, [editor])

  const resolveThread = useCallback(threadId => {
    editor.commands.resolveThread({ id: threadId })
  }, [editor])

  const unresolveThread = useCallback(threadId => {
    editor.commands.unresolveThread({ id: threadId })
  }, [editor])

  const updateComment = useCallback((threadId, commentId, content, metaData) => {
    editor.commands.updateComment({
      threadId, id: commentId, content, data: metaData,
    })
  }, [editor])

  const onHoverThread = useCallback(threadId => {
    hoverThread(editor, [threadId])
  }, [editor])

  const onLeaveThread = useCallback(() => {
    hoverOffThread(editor)
  }, [editor])

  if (!editor) {
    return null
  }

  const filteredThreads = threads.filter(t => (showUnresolved ? !t.resolvedAt : !!t.resolvedAt))

  return (
    <ThreadsProvider
      onClickThread={selectThreadInEditor}
      onDeleteThread={deleteThread}
      onHoverThread={onHoverThread}
      onLeaveThread={onLeaveThread}
      onResolveThread={resolveThread}
      onUpdateComment={updateComment}
      onUnresolveThread={unresolveThread}
      selectedThreads={editor.storage.comments.focusedThreads}
      selectedThread={selectedThread}
      setSelectedThread={setSelectedThread}
      threads={threads}
    >
      <div className="col-group" data-viewmode={showUnresolved ? 'open' : 'resolved'}>
        <div className="main">
          <div className="control-group">
            <div className="button-group">
              <button onClick={createThread} disabled={editor.state.selection.empty}>Add comment</button>
              <button onClick={() => editor.chain().focus().setImage({ src: 'https://placehold.co/800x500' }).run()}>Add image</button>
            </div>
          </div>
          <EditorContent editor={editor} />
        </div>
        <div className="sidebar">
          <div className="sidebar-options">
            <div className="option-group">
              <div className="label-large">Comments</div>
              <div className="switch-group">
                <label>
                  <input type="radio" name="thread-state" onChange={() => setShowUnresolved(true)} checked={showUnresolved} />
                  Open
                </label>
                <label>
                  <input type="radio" name="thread-state" onChange={() => setShowUnresolved(false)} checked={!showUnresolved}/>
                  Resolved
                </label>
              </div>
            </div>
            <ThreadsList provider={provider} threads={filteredThreads} />
          </div>
        </div>
      </div>
    </ThreadsProvider>
  )
}

// 创建评论扩展配置
export const createCommentsExtension = (provider, onClickThread) => {
  return CommentsKit.configure({
    provider,
    useLegacyWrapping: false,
    onClickThread: (threadId) => {
      console.log('createCommentsExtension onClickThread called with:', threadId)
      
      // 添加安全检查
      try {
        if (onClickThread) {
          onClickThread(threadId)
        }
      } catch (error) {
        console.error('Error in onClickThread callback:', error)
      }
    },
    // 添加更安全的点击处理配置
    HTMLAttributes: {
      class: 'comment-thread',
    },
    // 禁用自动选择以避免位置冲突
    autoselect: false,
  })
}

// 评论按钮组件
export const CommentButton = ({ editor, disabled = false }) => {
  const [modalVisible, setModalVisible] = useState(false)
  const user = useUser()
  
  const handleOpenModal = useCallback(() => {
    if (!editor || editor.state.selection.empty) {
      return
    }
    setModalVisible(true)
  }, [editor])

  const handleConfirm = useCallback(async (content) => {
    if (!editor || !content) {
      return
    }

    editor.chain().focus().setThread({ 
      content, 
      commentData: { userName: user.name } 
    }).run()
    
    setModalVisible(false)
  }, [editor, user])

  const handleCancel = useCallback(() => {
    setModalVisible(false)
  }, [])

  return (
    <>
      <button 
        onClick={handleOpenModal} 
        disabled={disabled || editor?.state.selection.empty}
      >
        添加评论
      </button>
      <CommentInputModal
        visible={modalVisible}
        onConfirm={handleConfirm}
        onCancel={handleCancel}
        title="添加评论"
        placeholder="请输入评论内容..."
      />
    </>
  )
}

// 评论侧边栏组件
export const CommentsSidebar = ({ editor, provider, className = '' }) => {
  const [showUnresolved, setShowUnresolved] = useState(true)
  const [selectedThread, setSelectedThread] = useState(null)
  const threadsRef = useRef([])

  const user = useUser()
  const { threads = [] } = useThreads(provider, editor, user)

  threadsRef.current = threads

  const selectThreadInEditor = useCallback(threadId => {
    if (editor) {
      editor.chain().selectThread({ id: threadId }).run()
    }
  }, [editor])

  const deleteThread = useCallback(threadId => {
    if (provider) {
      provider.deleteThread(threadId)
    }
    if (editor) {
      editor.commands.removeThread({ id: threadId })
    }
  }, [editor, provider])

  const resolveThread = useCallback(threadId => {
    if (editor) {
      editor.commands.resolveThread({ id: threadId })
    }
  }, [editor])

  const unresolveThread = useCallback(threadId => {
    if (editor) {
      editor.commands.unresolveThread({ id: threadId })
    }
  }, [editor])

  const updateComment = useCallback((threadId, commentId, content, metaData) => {
    if (editor) {
      editor.commands.updateComment({
        threadId, id: commentId, content, data: metaData,
      })
    }
  }, [editor])

  const onHoverThread = useCallback(threadId => {
    if (editor) {
      hoverThread(editor, [threadId])
    }
  }, [editor])

  const onLeaveThread = useCallback(() => {
    if (editor) {
      hoverOffThread(editor)
    }
  }, [editor])

  if (!editor || !provider) {
    return null
  }

  const filteredThreads = threads.filter(t => (showUnresolved ? !t.resolvedAt : !!t.resolvedAt))

  return (
    <ThreadsProvider
      onClickThread={selectThreadInEditor}
      onDeleteThread={deleteThread}
      onHoverThread={onHoverThread}
      onLeaveThread={onLeaveThread}
      onResolveThread={resolveThread}
      onUpdateComment={updateComment}
      onUnresolveThread={unresolveThread}
      selectedThreads={editor.storage.comments?.focusedThreads || []}
      selectedThread={selectedThread}
      setSelectedThread={setSelectedThread}
      threads={threads}
    >
      <div className={`comments-sidebar ${className}`}>
        <div className="sidebar-options">
          <div className="option-group">
            <div className="label-large">评论</div>
            <div className="switch-group">
              <label>
                <input type="radio" name="thread-state" onChange={() => setShowUnresolved(true)} checked={showUnresolved} />
                未解决
              </label>
              <label>
                <input type="radio" name="thread-state" onChange={() => setShowUnresolved(false)} checked={!showUnresolved}/>
                已解决
              </label>
            </div>
          </div>
          <ThreadsList provider={provider} threads={filteredThreads} />
        </div>
      </div>
    </ThreadsProvider>
  )
}

// 创建评论提供者的工厂函数
export const createCommentsProvider = (docId, appId = import.meta.env.VITE_TIPTAP_APP_ID) => {
  const doc = new Y.Doc()
  const isDev = import.meta.env.MODE === 'development'
  const id = isDev ? `dev-${docId}` : docId || uuid()

  const provider = new TiptapCollabProvider({
    appId,
    name: `tiptap-comments-demo/${id}`,
    document: doc,
    connect:true, //初始化后连接到服务器
    broadcast: true, // 实现跨浏览器标签页的文档同步
    preserveConnection:true, // 关闭提供程序后保持 WebSocket 连接打开
    onOpen() {
      console.log('WebSocket connection opened.')
    },
    onConnect() {
      console.log('Connected to the server.')
    },
  })

  // 不应用初始内容，让协同编辑提供者自己处理
  // try {
  //   const initialBinary = fromBase64String(initialContent)
  //   Y.applyUpdate(provider.document, initialBinary)
  // } catch (error) {
  //   console.warn('Failed to apply initial content:', error)
  // }

  return { provider, doc }
}

export default TiptapCommentEditor